/*
 * CoreBean.java Created on Feb 16, 2003 11:05:00 AM
 *
 * Copyright (C) 2003 eRocX Software Group - www.erocx.com
 */
package com.erocx.c24;

import java.util.Calendar;
import java.util.Vector;

/**
 * <p>Title: CoreBean</p>
 * <p>Description: calculate the result to 24 with 4 int numbers</p>
 *
 * @author		<a href="mailto:eroclu@gmail.com">Andy Lu</a>
 * @version   	1.0
 */

public final class CoreBean {
    private int _a, _b, _c, _d;
    private char[] operators = {'+', '-', '*', '/'};   //4 operators
    private int[] operator_seq = new int[64];          //64 operator sequences (4^3)

    private int trees[] = {               //calculation sequence
        1, /* (((a.b).c).d) */
        2, /* ((a.(b.c)).d) */
        3, /* ((a.b).(c.d)) */
        4, /* (a.((b.c).d)) */
        5  /* (a.(b.(c.d))) */
    };

    private int[][] permutes = {            //24 permutations of 4 numbers
        {1,2,3,4},{1,2,4,3},{1,3,2,4},{1,3,4,2},{1,4,2,3},{1,4,3,2},
        {2,1,3,4},{2,1,4,3},{2,3,1,4},{2,3,4,1},{2,4,1,3},{2,4,3,1},
        {3,1,2,4},{3,1,4,2},{3,2,1,4},{3,2,4,1},{3,4,1,2},{3,4,2,1},
        {4,1,2,3},{4,1,3,2},{4,2,1,3},{4,2,3,1},{4,3,1,2},{4,3,2,1}
    };

    private int[][] operandPermute = new int[24][4];

    private boolean flag = true;
    private boolean existAnswer = false;
    private Vector answer = new Vector();

    public CoreBean() {
        initOperatorSequence();
    }

    //initialize operator sequence
    private void initOperatorSequence() {
        for(int i = 0; i < 4; i ++)
            for(int j = 0; j < 4; j ++)
                for(int k = 0; k < 4; k ++)
                    operator_seq[i * 16 + j * 4 + k] = operators[i] * 65536 + operators[j] * 256 + operators[k];
    }

    //initialize operand permute
    private void initOperandPermute() {
        int[] operands = new int[5];
        for (int i = 0; i < 24; i ++) {
            operands[permutes[i][0]] = _a;
            operands[permutes[i][1]] = _b;
            operands[permutes[i][2]] = _c;
            operands[permutes[i][3]] = _d;

            operandPermute[i][0] = operands[1];
            operandPermute[i][1] = operands[2];
            operandPermute[i][2] = operands[3];
            operandPermute[i][3] = operands[4];
        }
    }

    private boolean isEqual(double a, double b) {
        return Math.abs(a - b) < 0.0000001 ? true : false;
    }

    private double calculate(double a, double b, int operator) {
        switch((char)operator) {
            case '+':
                return a + b;
            case '-':
                return a - b;
            case '*':
                return a * b;
            case '/':
                if (b != 0) {
                    flag = true;
                    return a / b;
                } else { //divide overflow
                    flag = false;
                    return 1;
                }
            default:
                flag = false;
                System.out.println("operator error!\n");
                return 1;
        }
    }

    public void caculate24(int aa, int bb, int cc, int dd) {
        existAnswer = false;
        answer.removeAllElements();
        setOperands(aa, bb, cc, dd);
        initOperandPermute();
        double result = 0;
        int a, b, c, d;
        int[] cur_operators = new int[3];

        for (int j = 0; j < 64; j ++) {
            int operator_3 = operator_seq[j];
            cur_operators[0] = operator_3 / 65536;
            cur_operators[1] = (operator_3 % 65536) / 256;
            cur_operators[2] = operator_3 % 256;

            for (int k = 0; k < 24; k++) {
                a = operandPermute[k][0];
                b = operandPermute[k][1];
                c = operandPermute[k][2];
                d = operandPermute[k][3];

                for (int i = 0; i < 5; i++) {
                    if (i == 0) {
                        result = calculate(calculate(calculate(a, b, cur_operators[0]), c, cur_operators[1]), d, cur_operators[2]);
                    }
                    if (i == 1) {
                        result = calculate(calculate(a, calculate(b, c, cur_operators[1]), cur_operators[0]), d, cur_operators[2]);
                    }
                    if (i == 2) {
                        result = calculate(calculate(a, b, cur_operators[0]), calculate(c, d, cur_operators[2]), cur_operators[1]);
                    }
                    if (i == 3) {
                        result = calculate(a, calculate(calculate(b, c, cur_operators[1]), d, cur_operators[2]), cur_operators[0]);
                    }
                    if (i == 4) {
                        result = calculate(a, calculate(b, calculate(c, d, cur_operators[2]), cur_operators[1]), cur_operators[0]);
                    }
                    if (isEqual(result, (double)24) && flag) {
                        existAnswer = true;
                        printResult(j, k, i);
                    }
                }
            }
        }
    }

    private void printResult(int j, int k, int i) {
        String result = null;
        int a, b, c, d;
        char[] cur_operators = new char[3];

        int operator_3 = operator_seq[j];
        cur_operators[0] = (char)(operator_3 / 65536);
        cur_operators[1] = (char)((operator_3 % 65536) / 256);
        cur_operators[2] = (char)(operator_3 % 256);

        a = operandPermute[k][0];
        b = operandPermute[k][1];
        c = operandPermute[k][2];
        d = operandPermute[k][3];

        if (i == 0) {
            result = "((" + a + cur_operators[0] + b + ")" + cur_operators[1] + c + ")" + cur_operators[2] + d + "";
        }
        if (i == 1) {
            result = "(" + a + cur_operators[0] + "(" + b + cur_operators[1] + c + "))" + cur_operators[2] + d + "";
        }
        if (i == 2) {
            result = "(" + a + cur_operators[0] + b + ")" + cur_operators[1] + "(" + c + cur_operators[2] + d + ")";
        }
        if (i == 3) {
            result = "" + a + cur_operators[0] + "((" + b + cur_operators[1] + c + ")" + cur_operators[2] + d + ")";
        }
        if (i == 4) {
            result = "" + a + cur_operators[0] + "(" + b + cur_operators[1] + "(" + c + cur_operators[2] + d + "))";
        }
        answer.add(result);
        //System.out.println(_a+""+_b+""+_c+""+_d + "---" + result);
    }

    public boolean isExistAnswer() {
        return existAnswer;
    }

    public String getAAnswer() {
        if (answer == null || answer.isEmpty())
            return null;

        return (String) answer.get(0);
    }

    private void setOperands(int a, int b, int c, int d) {
        _a = a;
        _b = b;
        _c = c;
        _d = d;
    }

    public static void main(String[] args) {
        //CoreBean coreBean = new CoreBean();
        //coreBean.caculate24(8, 6, 7, 7);
        //System.out.println(coreBean.isExistAnswer());
        Calendar cal = Calendar.getInstance();

        cal.set(2000, 8, 1);
        int day = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        System.out.println(day);
    }

}